﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Module_Persistence;
using Module_Basic_Entities;
using AIniciacao.Lib.Sprites;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using AIniciacao.Lib.CutScenes;
using AIniciacao.Lib.Panel.StatusBar;
using System.Collections;
using AIniciacao.Lib.Characters;
using AIniciacao.Lib.GameUtils;
using AIniciacao.Screens;
using AIniciacao.Triggers;
using AIniciacao.Lib.Audio;

namespace AIniciacao
{
    public static class World
    { 
        #region variables declaration
        public static Personagem Detetive { get; set; }
        public static List<Map2D> Map2dList { get; set; }
        public static CutScene CurrentCutSceneMessages{ get; set; }
        public static CutSceneScreen CurrentCutSceneScreen { get; set; }
        public static Map2D CurrentMap { get; set; }
        public static SpriteBatch SpriteBatch { get; set; }
        public static ContentManager Content { get; set; }
        public static GraphicsDevice GraphicsDevice { get; set; }
        public static WorldTime Time { get; set; }
        public static HealthBar HealthBar { get; set; }
        public static GameState GameState { get; set; }
        public static List<AnimatedTile> CurrentAnimatedTiles{get;set;}
        public static IDictionary<String, CutScene> CutScenes;
        public static IDictionary<int, Trigger> Triggers;
        public static IDictionary<int, List<String>> FootstepsSounds;
        public static IDictionary<int, List<String>> AmbienceSounds;
        public static List<String> CurrentFootstepSound;
        public static KeysBar KeysBar { get; set; }
     
        #endregion

        #region Loaders

        public static void LoadCutSceneScreen(String cutSceneName)
        {
            World.LoadCutScenes();
            CutSceneScreen cutSceneScreen = new CutSceneScreen(World.CutScenes[cutSceneName],Color.Red);
            World.CurrentCutSceneScreen = cutSceneScreen;
            
        }
        public static void LoadSounds()
        {
            FootstepsSounds = new Dictionary<int, List<String>>();
            FootstepsSounds.Add(1, new List<string>() {GamePathObjects.ConcreteFootsteps01SoundPath,
                                                 GamePathObjects.ConcreteFootsteps02SoundPath,
                                                 GamePathObjects.ConcreteFootsteps03SoundPath,
                                                 GamePathObjects.ConcreteFootsteps04SoundPath,
                                                 GamePathObjects.ConcreteFootsteps05SoundPath,
                                                });
            LoadSoundsToAudioManager(FootstepsSounds);
            
            CurrentFootstepSound = FootstepsSounds[1];
        }
        public static void LoadSoundsToAudioManager(IDictionary<int,List<String>> Hash)
        {
            foreach (int reg in Hash.Keys)
            {
                IList<String> regSounds = Hash[reg];
                for (int pathFoot = 0; pathFoot < regSounds.Count; pathFoot++)
                    AudioFactory.audioManager.LoadSound(regSounds[pathFoot]);
            }
        }
        //TODO
        public static void LoadAmbients()
        {
            
        
        }

        public static void LoadTriggers()
        {
            Triggers = new Dictionary<int, Trigger>();
            Triggers.Add(GameConstants.PowerUpTriggerIndex, new PowerUpTrigger());
            Triggers.Add(GameConstants.PowerDownTriggerIndex, new PowerDownTrigger());
            Triggers.Add(GameConstants.OpenDoorTriggerIndex, new OpenDoorTrigger());
            Triggers.Add(GameConstants.DeathTriggerIndex, new DeathTrigger());

        }   
        public static void LoadCutScenes()
        {
            CutScenes = new Dictionary<String, CutScene>();
            CutScenes.Add(GameConstants.NewYorkCutSceneIndex,Content.Load <CutScene>(GamePathObjects.NewYorkCutScenePath));
            CutScenes.Add(GameConstants.BeginCutSceneIndex, Content.Load<CutScene>(GamePathObjects.BeginCutScenePath));
        }
        
        public static void LoadMap(string mapAssetName,string animAssetName )
        {
            CurrentMap = Content.Load<Map2D>(mapAssetName);
            CurrentAnimatedTiles=Content.Load<List<AnimatedTile>>(animAssetName);
           
           
            for (int animTiles = 0; animTiles < CurrentAnimatedTiles.Count;  animTiles++ )
            {
                AnimatedTile tile = CurrentAnimatedTiles[animTiles];
                if (tile.repeatline > 0)
                {
                    int firstline = tile.line;
                    for (int repeat = 0; repeat < tile.repeatline; repeat++)
                    {

                        CurrentAnimatedTiles.Add(new AnimatedTile(tile.type, tile.delay, firstline++, tile.column, tile.frames));
                    }
                }
                if (tile.repeatcolumn > 0)
                {
                    int firstcolumn = tile.column;
                    for (int repeat = 0; repeat < tile.repeatcolumn; repeat++)
                    {

                        CurrentAnimatedTiles.Add(new AnimatedTile(tile.type, tile.delay, tile.line, firstcolumn++, tile.frames));
                    }
                }

            }
            (CurrentMap.GetLayerAt(0) as Layer2D).AnimatedTiles = CurrentAnimatedTiles;
        }
        public static void LoadKeysBar()
        {
            List<Color> color = new List<Color>();
            color.Add(Color.Gray);
            List<Vector2> vector2 = new List<Vector2>();
            vector2.Add(new Vector2(200, 200));
            List<Texture2D> textures = new List<Texture2D>();
            textures.Add(World.Content.Load<Texture2D>(GamePathObjects.BarraPath));
            KeysBar = new KeysBar(textures, color, vector2);
            KeysBar.SBatch = SpriteBatch;
        }

        public static void LoadHealthBar()
        {
            HealthBar = new HealthBar(
                           GameConstants.AmountOfHealth, GameConstants.MaxHealth,
                           Content.Load<Texture2D>(GamePathObjects.BarraPath),
                           Content.Load<Texture2D>(GamePathObjects.HealthPath),
                           GameConstants.BoxPosition,
                           GameConstants.HealthPosition,
                           Color.GreenYellow,
                           Color.Red, 
                           GameConstants.HealthRecovery,
                           GameConstants.RecoveryFactor,
                           GameConstants.BoxFlip,
                           GameConstants.HeathFlip);
            HealthBar.SBatch = SpriteBatch;

        }
        public static void LoadDetective()
        {            
            Texture2D imgUp = Content.Load<Texture2D>(GamePathObjects.StanleyUpPath);
            Texture2D imgRight = Content.Load<Texture2D>(GamePathObjects.StanleyRightPath);
            Texture2D imgLeft = Content.Load<Texture2D>(GamePathObjects.StanleyLeftPath);
            Texture2D imgDown = Content.Load<Texture2D>(GamePathObjects.StanleyDownPath);
            Texture2D imgPerfil = Content.Load<Texture2D>(GamePathObjects.StanleyPerfilPath);

            PersonagemAnimation personagemAnimations = new PersonagemAnimation();
            Animation runCima = new Animation(imgUp, 
                                             GameConstants.StanleyAnimationUpFramesPerSecond, 
                                             GameConstants.StanleyAnimationUpAmountOfColumns,
                                             GameConstants.StanleyAnimationUpAmounfOfLines,
                                             GameConstants.StanleyAnimationUpFrameWidth,
                                             GameConstants.StanleyAnimationUpFrameHeight,
                                             Point.Zero,
                                             GameConstants.StanleyAnimationUpLoop);
            Animation runBaixo = new Animation(imgDown, 
                                             GameConstants.StanleyAnimationDownFramesPerSecond,
                                             GameConstants.StanleyAnimationDownAmountOfColumns,
                                             GameConstants.StanleyAnimationDownAmounfOfLines,
                                             GameConstants.StanleyAnimationDownFrameWidth,
                                             GameConstants.StanleyAnimationDownFrameHeight,
                                             Point.Zero,
                                             GameConstants.StanleyAnimationDownLoop);
            
            Animation runEsq = new Animation(imgLeft,
                                             GameConstants.StanleyAnimationLeftFramesPerSecond,
                                             GameConstants.StanleyAnimationLeftAmountOfColumns,
                                             GameConstants.StanleyAnimationLeftAmounfOfLines,
                                             GameConstants.StanleyAnimationLeftFrameWidth,
                                             GameConstants.StanleyAnimationLeftFrameHeight,
                                             Point.Zero,
                                             GameConstants.StanleyAnimationLeftLoop);
            Animation runDir = new Animation(imgRight,
                                             GameConstants.StanleyAnimationRightFramesPerSecond,
                                             GameConstants.StanleyAnimationRightAmountOfColumns,
                                             GameConstants.StanleyAnimationRightAmounfOfLines,
                                             GameConstants.StanleyAnimationRightFrameWidth,
                                             GameConstants.StanleyAnimationRightFrameHeight,  
                                             Point.Zero,
                                             GameConstants.StanleyAnimationRightLoop);
            Animation ficar = new Animation(imgPerfil,
                                            GameConstants.StanleyAnimationStayFramesPerSecond,
                                            GameConstants.StanleyAnimationStayAmountOfColumns,
                                            GameConstants.StanleyAnimationStayAmounfOfLines,
                                            GameConstants.StanleyAnimationStayFrameWidth,
                                            GameConstants.StanleyAnimationStayFrameHeight,
                                            Point.Zero,
                                            GameConstants.StanleyAnimationRightLoop);
            personagemAnimations.AddAnimation(ficar, "fica");
            personagemAnimations.AddAnimation(runCima, "correc");
            personagemAnimations.AddAnimation(runBaixo, "correb");
            personagemAnimations.AddAnimation(runEsq, "corree");
            personagemAnimations.AddAnimation(runDir, "corred");
            personagemAnimations.currentAnimation = "fica";
            Detetive = new Stanley(imgPerfil,imgLeft,imgRight,imgUp,imgDown,
                                   GameConstants.StanleyInitialPosition, 
                                   GameConstants.StanleyInitialVelocity, 
                                   personagemAnimations);
        }
        #endregion

        #region Drawers
        public static void Draw(GameTime gameTime)
        {
            DrawMap(gameTime);
            DrawCharacters();
            HealthBar.Draw();
            KeysBar.Draw();
        }
        public static void DrawMap(GameTime gameTime)
        {
            SpriteBatch.Draw((float)gameTime.ElapsedGameTime.TotalSeconds, CurrentMap, new Vector2(Detetive.PosDet.X * -1, Detetive.PosDet.Y * -1), Color.White);
        }
        private static void DrawCharacters()
        {
            Detetive.PersonagemAnimations.Draw(SpriteBatch);
            
        }
        #endregion Drawers

        #region Updaters
        public static void Update(GameTime gameTime)
        {
            HealthBar.Update(gameTime);
            KeysBar.Update(gameTime);
            Detetive.PersonagemAnimations.Update(gameTime);
            Time.Update(gameTime);
            
            foreach(AnimatedTile animBlock in CurrentAnimatedTiles)
            {
                animBlock.updateAnimation();
            }
    
        }
        public static Tile? getCurrentTile()
        {
            float tileIndexX = Detetive.PosDet.X + GameConstants.StanleyCollisionDiff;
            float tileIndexY = Detetive.PosDet.Y + GameConstants.StanleyCollisionDiff;
            Layer2D layer = CurrentMap.GetLayerAt(GameConstants.TerrainLayer) as Layer2D;
            return layer.ContainsTile(new Vector2(tileIndexX, tileIndexY));
        }


        #endregion
    }
}
